# -*- coding:utf-8 -*-
from ast import Str
from crypt import METHOD_SHA256
import json
import sqlite3
import sys,os
BASE = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0,BASE)
from SNetwork.StockRequest import StockRequest
from STool.StockTool import StockTool
from STool.StockTT import *


#先引入后面可能用到的library
import tushare as ts
import datetime
import time
from pymongo import MongoClient
from threading import Thread
from multiprocessing import Process

# from photo import photo

import pandas as pd
from stock_py.SysFile import Base_File_Oper

ROOT_PATH=os.path.abspath(os.path.dirname(os.getcwd()))
the_day = '20210820'  #截至计算时间

class StockTushare:
    def __init__(self):
        self.u_index=0
        #使用之前先输入token，可以从个人主页上复制出来，
        #每次调用数据需要先运行该命令
        ts.set_token(Base_File_Oper.read_tushare_token())
        self.pro = ts.pro_api()
        self.today_String = datetime.datetime.now().strftime('%Y-%m-%d')
        self.today_dt= datetime.datetime.strptime(self.today_String,'%Y-%m-%d')
        self.today_mt_string= datetime.datetime.now().strftime('%Y%m%d')
        self.today_mt=datetime.datetime.strptime(self.today_mt_string, '%Y%m%d')  
        self.lastweek_date=self.today_mt-datetime.timedelta(days=60)
        self.lastweek_date_str=datetime.datetime.strftime(self.lastweek_date, '%Y%m%d')  
        
        self.client = MongoClient('mongodb://127.0.0.1:27017/')
        # self.client = MongoClient('mongodb://yangwende:QAZqaz114322@82.157.232.243:27017/tushare')
        self.lastyear_date=self.today_mt-datetime.timedelta(days=365)
        self.lastyear_date_str=datetime.datetime.strftime(self.lastyear_date, '%Y%m%d')  
        self.db = self.client.tushare
        self.stock_basic_aa = self.db['stock_basic_aa']
        self.stock_account = self.db['stock_account']
        self.xueqiu=StockRequest()


    #获取股票上市时长
    def get_stock_trade_days(self,list_date):
        list_date_temp=datetime.datetime.strptime(list_date,'%Y%m%d')
        date_len=self.today_dt-list_date_temp
        return date_len.days
    
    #是否新高
    def isNewHighForDateCount(self,close,count,sourceData):        # #如果存在大于当日价格的，则是非新高，所以数值要取非
        
        df1 = pd.DataFrame(sourceData)
        close_max = df1[0:count].close.max()
        if close >= close_max:
            return 1
        return 0

    # xx日最高收盘价
    def newHighForDateCount(self, count, sourceData):  #
        df1 = pd.DataFrame(sourceData)
        close_max = df1[0:count].close.max()
        return round(close_max ,3) #接近新高比例保留3位小数
    
    #近N日振幅是否小于20%
    def isWaveLow20ForDateCount(self,close,count,sourceData,percent=0.8):        # #如果存在大于当日价格的，则是非新高，所以数值要取非
        df1 = pd.DataFrame(sourceData)
        if len(df1)<=count+20:
            return 0
        close_max = df1[1:count+1].close.max()
        close_min = df1[1:count+1].close.min()
        if close_min >= (close_max*percent):
            return 1
        return 0
    
    def isLimitUpOrDown(self,ts_code,close,last_close,percent):
        mark_pect = 0.1
        if ts_code.startswith("300") or ts_code.startswith("688"):
            mark_pect = 0.2 #
        if ts_code.startswith("*S"):
            mark_pect = 0.05 #
        if ts_code.endswith("BJ"):
            mark_pect = 0.3 #
        if close >= last_close:
            #涨
            limit_close = RD(last_close*(1+mark_pect),2) #四舍五入保留两位小数
            limit_close_price = RD(last_close*mark_pect,2) #四舍五入保留两位小数
            limit_percent= RD(float(limit_close_price/last_close)*100,2)
            if close == limit_close:
                return 1
            else:
                return 0
        else:
            #跌
            limit_close = RD(last_close*(1-mark_pect),2) #四舍五入保留两位小数
            limit_close_price = RD(last_close*mark_pect,2) #四舍五入保留两位小数
            # limit_percent= RD(float(limit_close_price/last_close)*100,2)

            if close == limit_close:
                return -1
            else:
                return 0
            
    def initDailyItem(self,item):
        temp=item
        temp['isYearHigh']=0
        temp['is20High']=0
        temp['topHigh250'] = 0
        temp['topHigh120'] = 0
        temp['is60High']=0
        temp['is120High']=0
        temp['is20Wave']= -100
        temp['avail_3']= -100
        temp['avail_5']= -100
        temp['avail_10']= -100
        temp['avail_20']= -100
        temp['avail_60']= -100
        temp['avail_250']=-100
        temp['net_mf_amount']="0万"
        temp['buy_elg_amount']="0万"
        temp['buy_elg_percent']="0%"

        return temp
    
    #检测股票日K线数据
    def get_stock_trade(self,ts_code,list_date_days):
        
        stock_daily=self.xueqiu.requestXueQiuDaily(ts_code)
        all_trade_daily=[]
        data_count=len(stock_daily)

        if data_count == 0:
            print(("获取异常 %s" %(ts_code)))
            return [self.today_String,all_trade_daily]
    
        amount = self.xueqiu.requestAmountInflow(ts_code)

        if data_count == 1:
            item=self.initDailyItem(stock_daily[0])
            item.update(amount)
            trade_date = StockTool.stringFromconvertDateType(stock_daily[0]['trade_date'],'%Y%m%d','%Y-%m-%d')#当天交易日期
            all_trade_daily.append(item)
            return [trade_date,all_trade_daily]
        
        for index,item in enumerate(stock_daily):
            item=self.initDailyItem(item)
            close= item['close']
            if index == 0 :
                item.update(amount)

            if index<10 and len(stock_daily)>=251:  
                item['avail_3']= close/stock_daily[3]['close']-1                  
                item['avail_5']= close/stock_daily[5]['close']-1
                item['avail_10']= close/stock_daily[10]['close']-1
                item['avail_20']= close/stock_daily[20]['close']-1
                item['avail_60']= close/stock_daily[60]['close']-1
                item['avail_250']= close/stock_daily[250]['close']-1
                item['is20High'] = self.isNewHighForDateCount(close,20,stock_daily)
                item['is20Wave'] = self.isWaveLow20ForDateCount(close,20,stock_daily,0.8)
                item['topHigh250'] = self.newHighForDateCount(250, stock_daily)  # 250日最高价，只计算最近10天且有一年数据的
                item['topHigh120'] = self.newHighForDateCount(120, stock_daily)  # 120日最高价
            if index<20 and list_date_days>250:   
                   
                item['isYearHigh'] = self.isNewHighForDateCount(close,250,stock_daily)

            if index<10 and list_date_days>250:                    
                last_close=stock_daily[index+1]['close']
                percent=item['percent']
                item['limit_status']= self.isLimitUpOrDown(ts_code,close,last_close,percent)
            
            all_trade_daily.append(item)
            
        all_trade_daily = sorted(all_trade_daily,key = lambda e:e.__getitem__('trade_date'), reverse=True)
        trade_date = StockTool.stringFromconvertDateType(all_trade_daily[0]['trade_date'],'%Y%m%d','%Y-%m-%d')#当天交易日期
        return [trade_date,all_trade_daily]
    
    #检测股票日K线数据
    def get_stock_weakly(self,ts_code,list_date_days):
        
        stock_weekly=self.xueqiu.requestXueQiuDaily(ts_code,type="week")
        all_trade_weekly=[]
        data_count=len(stock_weekly)

        if data_count == 0:
            print(("获取异常 %s" %(ts_code)))
            return [self.today_String,all_trade_weekly]
    

        if data_count == 1:
            item=self.initDailyItem(stock_weekly[0])
            trade_date = StockTool.stringFromconvertDateType(stock_weekly[0]['trade_date'],'%Y%m%d','%Y-%m-%d')#当天交易日期
            all_trade_weekly.append(item)
            return [trade_date,all_trade_weekly]
        
        for index,item in enumerate(stock_weekly):
            item=self.initDailyItem(item)
            close=item['close']
            if index<3 and len(stock_weekly)>=10: 
                item['percent_red']= 1 if item['close'] >= item['open'] else 0            
                item['avail_5']= close/stock_weekly[5]['close']-1
            all_trade_weekly.append(item)
            
        all_trade_weekly = sorted(all_trade_weekly,key = lambda e:e.__getitem__('trade_date'), reverse=True)
        trade_date = StockTool.stringFromconvertDateType(all_trade_weekly[0]['trade_date'],'%Y%m%d','%Y-%m-%d')#当天交易日期
        return [trade_date,all_trade_weekly]
    
    def ma_day(self,trade_kline,list_date_days):
        MA5=[0,0,0,0,0]                       
        MA30=[0,0,0,0,0]  
        MA60=[0,0,0,0,0] 
        if list_date_days >= 365:
            df = pd.DataFrame(trade_kline)
            CLOSE = df.close.values
            MA5=MA(CLOSE,5)                    
            MA30=MA(CLOSE,30) 
            MA60=MA(CLOSE,60) 
        if len(MA5) >= 6:
            MA5 = MA5[0:5]
        if len(MA30) >= 6:
            MA30 = MA30[0:5]
        if len(MA60) >= 6:
            MA60 = MA60[0:5] 
            
        m5 = ','.join(str(round(i,2)) for i in MA5)
        m30 = ','.join(str(round(i,2)) for i in MA30)
        m60 = ','.join(str(round(i,2)) for i in MA60)
        
        return [m5,m30,m60]
            
    def get_caiwu(self,ts_code):
        df = self.pro.fina_indicator(**{"ts_code": ts_code,"period": 20211231,}, fields=[
            "ts_code",
            "end_date",
            "grossprofit_margin",
            "netprofit_yoy",
            "dt_netprofit_yoy",
            "or_yoy",
            "roe_waa"
        ])
        print(df)
    
    def funcaaaaa(self,all_stocks,all_stock_count,singleObjc):
        
        for index,stock_info in enumerate(all_stocks):  

            start_time_0 = time.time()
            ts_code = stock_info['ts_code']
            ts_status = stock_info['list_status']
            #如果这个地方开始报错的话检查下本地数据库是否开启
            stock_local_info = self.stock_basic_aa.find_one({ "ts_code": ts_code })
            
            base_info = self.xueqiu.requestXueQiuBaseInfo(ts_code)#基础信息
            list_date_days=self.get_stock_trade_days(stock_info['list_date'])# #获取股票上市时长
            [trade_date,trade_kline] = self.get_stock_trade(ts_code,list_date_days)#获取起始日期到最新一天的日交易数据
            [trade_date,trade_weekly_kline] = self.get_stock_weakly(ts_code,list_date_days)#获取起始日期到最新一天的周交易数据

            
            [m5,m30,m60] = self.ma_day(trade_kline,list_date_days)
            [m5_w,m30_w,m60_w] = self.ma_day(trade_weekly_kline,list_date_days)
            
            chicang = self.xueqiu.requestORGFor(ts_code)#获取基金持仓 每月请求一次即可
            # caiwu = self.get_caiwu(ts_code)
            if stock_local_info != None:#本地数据库存在code
                #更新本地 交易K线，上市日期、持仓数据
                dt1={
                    # 'trade_daily':trade_kline[0:3] if len(trade_kline) >5 else [],
                    # 'trade_weekly_daily':trade_weekly_kline[0:3] if len(trade_weekly_kline) > 5 else [],
                    'trade_daily':trade_kline,
                    'trade_weekly_daily':trade_weekly_kline,
                    'ma5':m5,
                    'ma30':m30,
                    'ma60':m60,
                    'ma5_w':m5_w,
                    'ma30_w':m30_w,
                    'ma60_w':m60_w,
                    'list_date_days':list_date_days,
                    'trade_date':trade_date,
                    'status':ts_status,
                    'hy3':""
                }
                
                if not "hy" in stock_local_info.keys():
                    bankuai_info = self.xueqiu.requestBankuaiDaily(ts_code)#新股获取板块信息
                    dt1['hy']=bankuai_info['hy']
                
                new_dic = {}
                new_dic.update(dt1)
                new_dic.update(base_info)

                if chicang!=None:
                    new_dic.update(chicang)
                newvalues = { "$set": new_dic}  
                self.stock_basic_aa.update_one({ "ts_code": ts_code }, newvalues)
            else:
                bankuai_info = self.xueqiu.requestBankuaiDaily(ts_code)#新股获取板块信息
                dt1={
                    'trade_daily':trade_kline,
                    'trade_weekly_daily':trade_weekly_kline,
                    'ma5':m5,
                    'ma30':m30,
                    'ma60':m60,
                    'ma5_w':m5_w,
                    'ma30_w':m30_w,
                    'ma60_w':m60_w,
                    'hy':bankuai_info['hy'],
                    'hy2':bankuai_info['hy2'],
                    'hy3':"",
                    'list_date_days':list_date_days,
                    'trade_date':trade_date
                }
                #本地数据库不存在code
                stock_local_info = stock_info
                stock_local_info.update(dt1)
                stock_local_info.update(base_info)
                if chicang!=None:
                    stock_local_info.update(chicang)
                self.stock_basic_aa.insert_one(stock_local_info)
                
            stop_time_0 = time.time()
            cost_0 = stop_time_0 - start_time_0
            singleObjc.uindex = singleObjc.uindex+1
            singleObjc.haoshi += cost_0
            print("更新 %s %s 第 %s - %s 个 耗时 %s" %(ts_code,stock_info['name'],str(all_stock_count),str(singleObjc.uindex),cost_0))

            if singleObjc.uindex == all_stock_count:
                print("更新完成 总耗时 %s" %(singleObjc.haoshi/20))
                
    def updateStocks(self,size_array_codes,all_stock_count,singleObjc):
        #构建一个空的dataframe用来装数据
 
        threads = []  
        for index,small_codes_array in enumerate(size_array_codes):
            # print("开启线程 %s" %(str(index)))
            thre = Thread(target=self.funcaaaaa, args=(small_codes_array,all_stock_count,singleObjc))   # 创建一个线程
            threads.append(thre)
            thre.start()  # 运行线程
 
    def updateBK(self):
        print(" 同花顺数据 ")
        
        data_file = 'aaaa.xlsx' # Excel文件存储位置
        D = pd.read_excel(data_file)
        print(D)
        ts_codes = D.ts_code.values
        ts_bks = D.bk.values

        for index,ts_code in enumerate(ts_codes):
            bks = ts_bks[index].split("-")
            print(ts_code +" : "+ts_bks[index])
            stock_local_info = self.stock_basic_aa.find_one({ "ts_code": ts_code })
            if stock_local_info:
                bk=bks[0]+"-"+bks[1]+"-"+bks[2]
                new_dic = {'hy':bks[0],'hy2':bks[1],'hy3':bks[2],'bk':bk} 
                print(ts_code +" : "+bks[0]+" "+bks[1]+" "+bks[2])                      
                newvalues = { "$set": new_dic }  
                self.stock_basic_aa.update_one({ "ts_code": ts_code }, newvalues)
            

        
        exit(0)
       
    def updateZhishu(self):
        
        df = self.pro.index_daily(ts_code='000001.SH', start_date=self.lastweek_date_str, end_date=self.today_mt_string)
        df_dict = df.to_dict('records')
        df_dict = sorted(df_dict,key = lambda e:e.__getitem__('trade_date'), reverse=True)
        for index, item in enumerate(df_dict[0:1]):
            trade_date = df_dict[index]['trade_date']
            shangzheng = df_dict[index]['close']
            dic={
                "trade_date":trade_date,
                "shangzheng":shangzheng,
                "account":6.5111,
                "hushen":0,
                "chuangye":0,
                "kechuang":0,
            }
            self.stock_account.insert_one(dic)
        
            

    #涨跌幅股票
    def stock_limit_update(self): 
        
        df_date = self.pro.trade_cal(exchange='', start_date='20220901',end_date=datetime.datetime.now().strftime('%Y%m%d'), is_open='1')
        cal_dates = df_date.cal_date.values
 
        dates = StockTool.getNonRepeatList(cal_dates)
        dates.sort()

        value_date=[]
        up_limit_count=[]
        down_limit_count=[]
        for date in dates[-3:]:
            # if not date == "20221116":
            #     continue
            df1 = self.pro.limit_list_d(trade_date = date, fields='ts_code,trade_date,name,pct_chg,limit,up_stat')       
            # print(df1)     
            ts_codes = df1.ts_code.values
            limits = df1.limit.values
            up_stats = df1.up_stat.values
            pct_chgs = df1.pct_chg.values

            up_limit=[]
            down_limit=[]
            for index,ts_code in enumerate(ts_codes):
                stock_local_info = self.stock_basic_aa.find_one({ "ts_code": ts_code })
                list_date_days = stock_local_info["list_date_days"]
                
                up_stat = up_stats[index]
                if up_stat != None and str(up_stat.split("/")[-1]) == str(list_date_days-1): 
                    #上市到目前未开板
                    continue   
                
                pct_chg = pct_chgs[index]
                if pct_chg >=40:
                    #40以上的涨停板，可能是上市首日
                    continue
                # print(stock_local_info['name'])        
                if "ST" in stock_local_info['name']:
                    continue
                if limits[index] =='U':
                    up_limit.append(ts_code)
                elif limits[index] =='D':
                    # print(ts_code+""+stock_local_info["name"])
                    down_limit.append(ts_code)
            value_date.append(date.replace("2022", ""))
            up_limit_count.append(len(up_limit))
            down_limit_count.append(len(down_limit))

        
            print("%s 涨停板数量：%s  跌停板数量：%s" %(date,len(up_limit),len(down_limit)))
        print(value_date)
        print(up_limit_count)
        print(down_limit_count)
        photo.makePhoto(value_date,up_limit_count,down_limit_count)
        return [value_date,up_limit_count,down_limit_count]



    # def photo(self, date,up,down):
        
        

            

            
            

